package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mapper.EmpExprMapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.*;
import com.itheima.service.DeptService;
import com.itheima.service.EmpLogService;
import com.itheima.service.EmpService;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.baomidou.mybatisplus.extension.toolkit.Db.page;

@Slf4j
@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private EmpExprMapper empExprMapper;

    @Autowired
    private EmpLogService empLogService;

    @Autowired
    private DeptService deptService;

    @Override
    public PageResult<Emp> getPageResult(EmpQueryParam empQueryParam) {
        //1. 设置分页参数
        Page<Emp> page = Page.of(empQueryParam.getPage(), empQueryParam.getPageSize());

        // 根据最后修改时间倒序排序
        page.addOrder(OrderItem.desc("update_time"));
/*

        // 方式一：构建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(empQueryParam.getName() != null && !empQueryParam.getName().isEmpty(), Emp::getName, empQueryParam.getName())
                .eq(empQueryParam.getGender() != null, Emp::getGender, empQueryParam.getGender())
                .between(empQueryParam.getBegin() != null && empQueryParam.getEnd() != null, Emp::getEntryDate, empQueryParam.getBegin(), empQueryParam.getEnd());

        // 调用page方法完成分页查询
        page = empMapper.selectPage(page, queryWrapper); // 若需带条件，请构建 QueryWrapper 作为第二个参数
*/

        // 方式二：使用lambdaQuery方法构建查询条件 = 方式一：构建查询条件 + 调用page方法完成分页查询
        page = lambdaQuery().like(empQueryParam.getName() != null && !empQueryParam.getName().isEmpty(), Emp::getName, empQueryParam.getName())
                .eq(empQueryParam.getGender() != null, Emp::getGender, empQueryParam.getGender())
                .between(empQueryParam.getBegin() != null && empQueryParam.getEnd() != null, Emp::getEntryDate, empQueryParam.getBegin(), empQueryParam.getEnd())
                .page(page);

        // 获取员工集合
        List<Emp> emps = page.getRecords();

        // 获取所有员工的部门id
        List<Long> deptIds = emps.stream()
                .filter(emp -> emp.getDeptId() != null)
                .map(emp -> Long.valueOf(emp.getDeptId()))
                .toList();

        if (!deptIds.isEmpty()) {
            // 批量查询这些部门的信息
            List<Dept> depts = deptService.listByIds(deptIds);

            // 将部门名称封装到员工对象中
            emps.forEach(emp -> {
                depts.forEach(dept -> {
                    if (emp.getDeptId() != null && emp.getDeptId().equals(dept.getId())) {
                        emp.setDeptName(dept.getName());
                    }
                });
            });
        }

        //3. 封装分页结果
        return new PageResult<>(page.getTotal(), emps);
    }

    @Transactional(rollbackFor = Exception.class) //开启事务管理 - rollbackFor: 抛出什么异常回滚事务
    @Override
    public boolean save(Emp emp) {
        //1. 保存员工的基本信息
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.insert(emp);
        log.info("保存员工信息, {}", emp);

        //2. 保存员工的工作经历信息 --> 属于上面刚添加的员工的
        List<EmpExpr> exprList = emp.getExprList();
        if(exprList != null && !exprList.isEmpty()){ //有工作经历
            //遍历集合，设置员工id
            exprList.forEach(expr -> {
                expr.setEmpId(emp.getId());
            });
            empExprMapper.insertBatch(exprList);
        }
        return false;
    }

    @Override
    public List<Emp> list() {
        return empMapper.selectList(null);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Integer> ids) {
        //1. 删除员工的基本信息 异常！！！
        removeByIds(ids);

        //2. 删除员工的工作经历信息 ？？？
        empExprMapper.deleteByEmpIds(ids);
    }

    @Override
    public Emp getById(Integer id) {
        return empMapper.selectById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(Emp emp) {
        //1. 根据ID更新员工基本信息
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.updateById(emp);

        //2. 更新员工的工作经历信息(先删除, 再添加)
        //2.1 根据员工的id删除员工的工作经历
        empExprMapper.deleteByEmpIds(Arrays.asList(emp.getId()));
        //2.2 再添加员工的工作经历 (批量)
        List<EmpExpr> exprList = emp.getExprList();
        if(exprList != null && !exprList.isEmpty()){ //有工作经历
            //遍历集合，设置员工id
            exprList.forEach(expr -> {
                expr.setEmpId(emp.getId());
            });
            empExprMapper.insertBatch(exprList);
        }
    }

    @Override
    public JobOption getEmpJobData() {
        // [{pos=教研主管, num=1} {pos=讲师, num=14}  {pos=学工主管, num=1} ...]
        List<Map> jobDataList = empMapper.getEmpJobData();

        // 组装数据 JobOption
        List jobList = jobDataList.stream().map(map -> {
            return map.get("pos");
        }).toList();

        List dataList = jobDataList.stream().map(map -> {
            return map.get("num");
        }).toList();
        return new JobOption(jobList, dataList);
    }


    @Override
    public List<Map<String, Object>> getEmpGenderData() {
        List<Map<String, Object>> mapList = empMapper.getEmpGenderData();
        return mapList;
    }

    @Override
    public LoginInfo login(Emp emp) {
        //1. 查询数据库, 根据用户名和密码查询员工信息
        Emp e = empMapper.getByUsernameAndPassword(emp);

        //2. 判断员工是否存在, 如果存在, 则说明登录成功; 封装返回结果
        if(e != null){
            //生成jwt令牌
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("id", e.getId());
            dataMap.put("username", e.getUsername());
            String jwt = JwtUtils.generateJwt(dataMap);//生成jwt令牌 - 存储id,username

            return new LoginInfo(e.getId(), e.getUsername(), e.getName(), jwt);
        }
        return null;
    }
}
